#ifndef __FRAME_DRIVCE_H__
#define __FRAME_DRIVCE_H__

#include "stm32f10x.h"
#include <stdbool.h>

// Frame结构体

#define FRAME_FIFO_SIZE               600      // 一级接收FIFO 尺寸 建议为帧大小的2倍以上
#define FRAME_FRAME_QUEUE_SIZE        3        // 帧队列大小
#define FRAME_FRAME_SIZE              300      // 帧大小

// ------------- 用户实现函数部分 -------------------------

// 用户定义宏部分
#define FRAME_CMD_POS     3   // 命令字 所在位置数组下标
#define FRAME_LEN_POS     4   // 帧长度 所在位置数组下标
#define FRAME_CMD_STX  0x55   // 帧头
#define FRAME_GET_TOT_LEN(x)   (x + 6)   //帧总长度  2019-9-19 修改 by wang
#define FRAME_GET_CHECK_POS(x)  (x + 5)  //帧校验值所在下标位置 2019-9-19 修改 by wang

// 指令处理使用
#define FRAME_BOARD_ID_POS    5
#define FRAME_BOARD_PATH_POS  6

// 帧解码用状态（使用状态机解码帧时使用）
typedef enum
{
	FIFO_STATE_FIND_STX = 0,   // 找指令头
	FIFO_STATE_FIND_LEN,       // 找帧长度
	FIFO_STATE_CHECK_FRAM,     // 校验帧
	FIFO_STATE_FIND_EXT,       // 找帧尾
}FIFO_STATE;


// UART命令帧定义
typedef struct FRAME_device_frame_cb
{
	volatile uint8_t	buff[FRAME_FRAME_SIZE];	// 命令帧缓冲区 
	volatile uint16_t	length;									// 命令帧有效数据个数
	volatile uint16_t	deviceID;
}FRAME_FRAME_CB;

// 帧队列结构体定义
typedef struct FRAME_device_frame_queue_cb
{
	FRAME_FRAME_CB queue[FRAME_FRAME_QUEUE_SIZE];
	volatile uint16_t head;						// 队列头索引
	volatile uint16_t end; 						// 队列尾索引
	volatile uint16_t index;					// 当前待发送数据在命令帧中的索引号
	
}FRAME_FRAME_QUEUE;

// Fifo结构体
typedef struct FRAME_device_fifo_cb
    {
        volatile uint8_t	buff[FRAME_FIFO_SIZE];
        volatile uint16_t	head;
        volatile uint16_t	end;
        uint16_t   length;					// 当前Fifo中数据个数
}FRAME_FIFO_CB;
typedef struct FRAME_device_fun_cb FRAME_DEVICE_CB;
// 函数结构体
typedef struct FRAME_device_fun_cb
{	    
	// 帧指令处理函数  (从帧队列中取出帧，并且进行处理)
	void (*FrameProcessCmd)(FRAME_FRAME_CB *frame, FRAME_DEVICE_CB *device);
	
	// 帧解析函数 （从Fifo中解析帧，并存入帧队列）
	void (*FrameProcessDecode)(FIFO_STATE *state,FRAME_FRAME_CB *frame ,FRAME_FIFO_CB *fifo, uint8_t (*FrameCheckValue)(FRAME_FRAME_CB *frame));
	
	// 校验码计算函数
	uint8_t (*FrameCheckValue)(FRAME_FRAME_CB *frame);
	
	// 存入一个字节存入Fifo, 用于RX 向Fifo存入
	void (*FifoPushByte);

	// 读取一个字节取出Fifo，用于TX 从Fifo取出
	void (*FifoPopByte);
	
	// 结构体部分
	FIFO_STATE fifoState;       // 帧状态机
	
	FRAME_FIFO_CB fifo_rx;       // Fifo接收队列
	FRAME_FIFO_CB fifo_tx;       // Fifo发送队列
	
	FRAME_FRAME_QUEUE queue_rx;  // 帧队列
	FRAME_FRAME_QUEUE queue_tx;	
	
	volatile uint8_t  Busy;			 // 发送请求
	
}FRAME_DEVICE_CB;


//void FRAME_Test(); // 测试函数

// ------- 用户自定义部分 -------


void FRAME_FrameDecode(FIFO_STATE *state,FRAME_FRAME_CB *frame ,FRAME_FIFO_CB *fifo,uint8_t (*FrameCheckValue)(FRAME_FRAME_CB *frame));
uint8_t FrameCheck(FRAME_FRAME_CB *frame);
// ------- 对外接口 -------

// 初始化函数     main() 调用
void FRAME_Init(FRAME_DEVICE_CB *driver ,void (*Decode)(FIFO_STATE *state,FRAME_FRAME_CB *frame ,FRAME_FIFO_CB *fifo,uint8_t (*FrameCheckValue)(FRAME_FRAME_CB *frame)),uint8_t (*Check)(FRAME_FRAME_CB *frame),void (*FrameCmd)(FRAME_FRAME_CB *frame,FRAME_DEVICE_CB *device));

// 处理线程函数   while  中调用
void FRAME_Process(FRAME_DEVICE_CB *driver);

// ------- 模块使用 -------

//------- Frame -------
bool FRAME_FrameInit(FRAME_FRAME_CB *frame);                              // 帧初始化        
bool FRAME_FramePushQueue(FRAME_FRAME_CB *frame,FRAME_FRAME_QUEUE *queue);  // 加入帧到队列(用于转发)
bool FRAME_FramePopQueue(FRAME_FRAME_CB *frame,FRAME_FRAME_QUEUE *queue);  // 从队列中弹出帧(用于CMD处理)

//------- FrameQueue -------
bool FRAME_FrameQueueInit(FRAME_FRAME_QUEUE *queue);                      // 帧队列初始化
bool FRAME_FrameQueueIsEmpty(FRAME_FRAME_QUEUE *queue);
bool FRAME_FrameQueueIsFull(FRAME_FRAME_QUEUE *queue);
bool FRAME_FrameQueueGetSendChar(FRAME_FRAME_QUEUE *queue,uint8_t *ch);   // 获取队列中一个要发送的字符

// ------- Fifo -------
bool FRAME_FifoPush(uint8_t ch,FRAME_FIFO_CB *fifo);
bool FRAME_FifoPop(uint8_t *ch,FRAME_FIFO_CB *fifo);
void FRAME_FifoInit(FRAME_FIFO_CB *fifo);
bool FRAME_FifoIsEmpty(FRAME_FIFO_CB *fifo);
bool FRAME_FifoIsFull(FRAME_FIFO_CB *fifo);
bool FRAME_FifoGet(uint8_t *ch,uint8_t pos ,FRAME_FIFO_CB *fifo);
bool FRAME_FifoCopy(uint8_t *buf,uint8_t len ,FRAME_FIFO_CB *fifo);
bool FRAME_FifoRemove(uint8_t len ,FRAME_FIFO_CB *fifo);
#endif
